

-- =======================================================================================
-- VARS
-- =======================================================================================
tm = {};
tm.targetManager = {
	castIndex = nil,
	castCache = {},
	locked = {}
}
tm.targetFrameSize = 30;
tm.targetFrameSpacing = 5;
tm.raidIconPath = "Interface\\TargetingFrame\\UI-RaidTargetingIcons";
tm.targetOrder = {
	8, -- skull
	7, -- x
	4, -- triangle
	6, -- square
	3, -- diamond
	1, -- star
	2, -- circle
	5  -- moon
}
tm.targetIconCoords = {
	-- 1: yellow star (0, 0.25, 0, 0.25)
	[1] = {
		minX = 0,
		maxX = 0.25,
		minY = 0,
		maxY = 0.25
	},
	-- 2: orange circle (0.25, 0.5, 0, 0.25)
	[2] = {
		minX = 0.25,
		maxX = 0.5,
		minY = 0,
		maxY = 0.25
	},
	-- 3: purple diamond (0.5, 0.75, 0, 0.25)
	[3] = {
		minX = 0.5,
		maxX = 0.75,
		minY = 0,
		maxY = 0.25
	},
	-- 4: green triangle (0.75, 1, 0, 0.25)
	[4] = {
		minX = 0.75,
		maxX = 1,
		minY = 0,
		maxY = 0.25
	},
	-- 5: silver moon (0, 0.25, 0.25, 0.5)
	[5] = {
		minX = 0,
		maxX = 0.25,
		minY = 0.25,
		maxY = 0.5
	},
	-- 6: blue square (0.25, 0.5, 0.25, 0.5)
	[6] = {
		minX = 0.25,
		maxX = 0.5,
		minY = 0.25,
		maxY = 0.5
	},
	-- 7: red x (0.5, 0.75, 0.25, 0.5)
	[7] = {
		minX = 0.5,
		maxX = 0.75,
		minY = 0.25,
		maxY = 0.5
	},
	-- 8: wite skull (0.75, 1, 0.25, 0.5)
	[8] = {
		minX = 0.75,
		maxX = 1,
		minY = 0.25,
		maxY = 0.5
	}
}


-- =======================================================================================
-- GENERAL
-- =======================================================================================
function tm.print(msg)
   DEFAULT_CHAT_FRAME:AddMessage("|CFFFFFF7FTM: |r" .. msg,1,1,1);
end
function tm.printEr(msg)
   DEFAULT_CHAT_FRAME:AddMessage("|CFFFFFF7FTM |C00FF0000ERROR: |r" .. msg,1,1,1);
end

function tm.init()
	tm.print("Target Manager init");

	tm.createFrames();
	
	--tm.mainFrame:RegisterEvent("UNIT_COMBAT")
	tm.mainFrame:RegisterEvent("CHAT_MSG_COMBAT_HOSTILE_DEATH")
	--tm.mainFrame:RegisterEvent("RAID_TARGET_UPDATE")
			
	tm.mainFrame:RegisterEvent("UNIT_SPELLCAST_START")
	tm.mainFrame:RegisterEvent("UNIT_SPELLCAST_STOP")
	tm.mainFrame:RegisterEvent("UNIT_SPELLCAST_SUCCEEDED")
	
	tm.mainFrame:SetScript("OnEvent", tm.mainFrameOnEvent)
  
  tm.test_createTestStuff()
end


-- ----------
-- main events

function tm.mainFrameOnEvent(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10)

		-- ----------
		-- spellcast START
		if (event == "UNIT_SPELLCAST_START") then
			tm.print("spellcast start: " .. arg3)
			local unitTarget = arg3.."target"
			if not GetRaidTargetIndex(unitTarget) then
				idx = tm.requestTargetAdd()
				SetRaidTarget(unitTarget, idx)
				table.insert(tm.targetManager.castCache, {unit = arg3, target = idx})
			end
		end
		
		-- ----------
		-- spellcast STOP
		if (event == "UNIT_SPELLCAST_STOP") then
		tm.print("spellcast stop: " .. arg3)
			local unit = arg3
			local unitTarget = arg3.."target"
			local ccIdx = tm.findUnitInCastCache(unit)
			
			if not tm.isTargetLocked(idx) then
				if ccIdx > 0 then
					tm.removeTargetByIcon(tm.targetManager.castCache[ccIdx].target)
					SetRaidTarget(unit.."target", 0)
					table.remove(tm.targetManager.castCache[ccIdx])
				end
			end
		end
		
		-- ----------
		-- spellcast SUCCEEDED
		if (event == "UNIT_SPELLCAST_SUCCEEDED") then
		tm.print("spellcast succeeded: " .. arg3)
			tm.lockTarget(arg3)
		end

		-- npc DEATH
		if arg2 == "CHAT_MSG_COMBAT_HOSTILE_DEATH" then
			local idx = GetRaidTargetIndex("target")
			if idx and UnitIsDead("target") then
				tm.removeTargetByIcon(idx)
				SetRaidTarget("target", 0)
			end
		end
		
		
		if false then
			if arg2 then
				tm.print("arg2: " .. arg2)
			end
	
			if arg3 then
				tm.print("arg3: " .. arg3)
			end
			
			if arg4 then
				tm.print("arg4: " .. arg4)
			end
			
			if arg5 then
				tm.print("arg5: " .. arg5)
			end
			
			if arg6 then
				tm.print("arg6: " .. arg6)
			end
			
			if arg7 then
				tm.print("arg7: " .. arg7)
			end
			
			if arg8 then
				tm.print("arg8: " .. arg8)
			end
			
			if arg9 then
				tm.print("arg9: " .. arg9)
			end
		
			if arg10 then
				tm.print("arg10: " .. arg10)
			end
		tm.print("===========================")
		tm.print("")
	end
end

-- =======================================================================================
-- UI
-- =======================================================================================
function tm.setRaidIconTexture (texture, idx)

	-- 1: yellow star			2: orange circle			3: purple diamond			4: green triangle
	-- 5: silver moon			6: blue square				7: red x							8: white skull
	
	local minX = tm.targetIconCoords[idx].minX;
	local maxX = tm.targetIconCoords[idx].maxX;
	local minY = tm.targetIconCoords[idx].minY;
	local maxY = tm.targetIconCoords[idx].maxY;
	
	texture:SetTexCoord(minX, maxX, minY, maxY)
end

function tm.setTargetFrameToIcon(frame, idx)
	if (idx >= 1) and (idx <= 8) then
		tm.setRaidIconTexture(tm.targetFrames[frame].textures.icon, idx)
	else
		tm.printEr("attempt to set raid icon failure: Index out of range")
	end
end

function tm.createFrames()
	tm.targetFrames = {};
	
	-- ----------
	-- main frame
	tm.mainFrame = CreateFrame("Frame", nil, UIParent);	
	tm.mainFrame:SetWidth(tm.targetFrameSize * 1.75 + tm.targetFrameSpacing * 2)
	tm.mainFrame:SetHeight(tm.targetFrameSize * 8 + tm.targetFrameSize * 0.75 + tm.targetFrameSpacing * 2)
	tm.mainFrame:SetPoint("TOPLEFT", "UIParent", "CENTER", 50, 50)
	tm.mainFrame:RegisterForDrag("LeftButton");
	tm.mainFrame:EnableMouse(true)
	tm.mainFrame:SetMovable(true)
	if false then
		tm.mainFrame:SetBackdrop({
			bgFile = "Interface\\TutorialFrame\\TutorialFrameBackground",
			edgeFile = "Interface\\Tooltips\\UI-Tooltip-Border",
			tile = true, tileSize = 16, edgeSize = 16,
			insets = { left = 4, right = 4, top = 4, bottom = 4 }
			})
		tm.mainFrame:SetBackdropColor(1,1,1,0.5)
	end
	
	tm.mainFrame:SetScript("OnDragStart", function()
		this:StartMoving();
		this.isMoving = true;
		end)
	tm.mainFrame:SetScript("OnDragStop", function()
		this:StopMovingOrSizing();
		this.isMoving = false;
		end)
	
	-- create the first target frame
	tm.targetFrames[1] = {
		frame = tm.createTargetFrame(tm.mainFrame, true)
	}
	tm.targetFrames[1].frame:SetWidth(tm.targetFrameSize*1.75)
	tm.targetFrames[1].frame:SetHeight(tm.targetFrameSize*1.75)
	tm.targetFrames[1].frame:SetPoint("TOPLEFT", tm.mainFrame, "TOPLEFT", tm.targetFrameSpacing, -tm.targetFrameSpacing)
	
	-- create the other target frames
	for x=2, 8, 1 do
		tm.targetFrames[x] = {
			frame = tm.createTargetFrame(tm.targetFrames[x-1].frame, false)
		}
	end
	
	-- create textures
	for x=1, 8, 1 do
		tm.targetFrames[x].textures = {
			icon = tm.createTargetFrameTextures(tm.targetFrames[x].frame)
		}
	end
	tm.targetFrames[1].textures.icon:SetHeight(tm.targetFrameSize * 1.25)
	tm.targetFrames[1].textures.icon:SetWidth(tm.targetFrameSize * 1.25)
		
	-- tm.setTargetTexturesToInital()
	tm.refreshTargetFrameIcons()
	
end

function tm.createTargetFrame(parent, showFrame)
	local frame = CreateFrame("Frame", nil, tm.mainFrame)
	frame:SetWidth(tm.targetFrameSize)
	frame:SetHeight(tm.targetFrameSize)
	frame:SetPoint("TOP", parent, "BOTTOM")
	if showFrame then
		frame:SetBackdrop({
			bgFile = "Interface\\TutorialFrame\\TutorialFrameBackground",
			edgeFile = "Interface\\Tooltips\\UI-Tooltip-Border",
			tile = true, tileSize = 16, edgeSize = 16,
			insets = { left = 4, right = 4, top = 4, bottom = 4 }
			})
	end
	
	return frame;
end

function tm.createTargetFrameTextures(frame)
	local texture = frame:CreateTexture(nil, "ARTWORK")
	texture:SetTexture(tm.raidIconPath)
	texture:SetPoint("CENTER", frame)
	texture:SetWidth(tm.targetFrameSize)
	texture:SetHeight(tm.targetFrameSize)
--	texture:SetTexCoord(0, 0.25, 0, 0.25)
	return texture;
end

function tm.setTargetTexturesToInital()
	for x = 1, 8 do
		tm.setTargetFrameToIcon(x,tm.targetOrder[x])
	end
end

function tm.refreshTargetFrameIcons()	
	if #tm.targetManager <= 8 then
		-- show and hide the appropriate frames
		for x = 1, 8, 1 do
			if x <= #tm.targetManager then
				tm.targetFrames[x].frame:Show();
			else
				tm.targetFrames[x].frame:Hide();
			end
		end
		
		-- set the frames to the correct icons
		for i,v in ipairs(tm.targetManager) do
			tm.setTargetFrameToIcon(i,v)
		end
	else
		tm.printEr("target manager out of bounds. current size: " .. #tm.targetManager)
	end
end

function tm.test_createTestStuff()
	-- ----------
	-- testButton1
	tm.testButton1 = CreateFrame("Button", nil, tmMainFrame, "UIPanelButtonTemplate");
	tm.testButton1:SetWidth(80)
	tm.testButton1:SetHeight(22)
	tm.testButton1:SetText("add")
	tm.testButton1:SetPoint("LEFT", tm.mainFrame, "RIGHT")
	tm.testButton1:SetScript("OnClick", function()
		tm.requestTargetAdd()
		end)
		
	-- ----------
	-- testButton2
	tm.testButton2 = CreateFrame("Button", nil, tmMainFrame, "UIPanelButtonTemplate");
	tm.testButton2:SetWidth(80)
	tm.testButton2:SetHeight(22)
	tm.testButton2:SetText("remove")
	tm.testButton2:SetPoint("TOP", tm.testButton1, "BOTTOM")
	tm.testButton2:SetScript("OnClick", function()
		tm.removeTargetByIndex(1)
		end)
	
	if false then
		-- ----------
		-- test frame
		tm.testFrame = CreateFrame("Frame", "tmTestFrame", UIParent);
		tm.testFrame:SetWidth(100)
		tm.testFrame:SetHeight(50)
		tm.testFrame:SetPoint("TOPLEFT", tm.mainFrame, "BOTTOMLEFT")
		tm.testFrame:SetBackdrop({
			-- bgFile = tm.raidIconPath,
			edgeFile = "Interface\\Tooltips\\UI-Tooltip-Border",
			tile = true, tileSize = 100, edgeSize = 16,
			insets = { left = 4, right = 4, top = 4, bottom = 4 }
			})
		
		-- ----------
		-- test frame test texture
		tm.testFrameTexture = tm.testFrame:CreateTexture("tmTestFrameTexture","ARTWORK")
		tm.testFrameTexture:SetTexture(tm.raidIconPath)
		tm.testFrameTexture:SetPoint("TOPLEFT", "tmTestFrame", "TOPLEFT")
		tm.testFrameTexture:SetWidth(100)
		tm.testFrameTexture:SetHeight(100)
	end
end


-- =======================================================================================
-- TARGET MANAGER
-- =======================================================================================
function tm.addTarget(icon)
	table.insert(tm.targetManager, icon)
	tm.refreshTargetFrameIcons()
end

function tm.removeTargetByIndex(slot)
	if (slot < 1) or (slot > 8) then
		tm.printEr("remove by index failed: index out of range")
	elseif (slot > #tm.targetManager) then
		tm.printEr("remove by index failed: index too high for current list")
	else
		table.remove(tm.targetManager, slot)
		tm.refreshTargetFrameIcons()
	end
end

function tm.removeTargetByIcon(icon)
	for i,v in ipairs(tm.targetManager) do
		if v == icon then
			table.remove(tm.targetManager, i)
			tm.refreshTargetFrameIcons()
			return
		end
	end
	tm.printEr("unable to remove by icon: icon not found")
end

function tm.requestTargetAdd()
	local found = false
	
	if #tm.targetManager == 8 then
		tm.print("Target Manager full, unable to add new target")
		return
	end
	
	for x = 1, 8, 1 do
		for i,v in ipairs(tm.targetManager) do
			if v == tm.targetOrder[x] then
				found = true
				break
			end
		end
		if not found then
			tm.addTarget(tm.targetOrder[x])
			return tm.targetOrder[x]
		else
			found = false
		end
	end
	
end

function tm.lockTarget(unit)
	local ccIdx = tm.findUnitInCastCache(unit)
	table.insert(tm.targetManager.locked, tm.targetManager.castCache[ccIdx].target)
	tm.targetManager.castIndex = nil;
end

function tm.isTargetLocked(idx)
	for i,v in ipairs(tm.targetManager.locked) do
		if v == idx then
			return true
		end
	end
	return false
end

function tm.findUnitInCastCache(unit)
	for i,v in ipairs(tm.targetManager.castCache) do
		if v.unit == unit then
			return i
		end
	end
	tm.printEr("find unit in cast cache failed: unit not found")
	return -1
end






tm.init();